package com.wedimob.scrapper.data;

/**
 * content type to retreive object extension.
 * 
 * @author melouadi
 * 
 */
public class ContentType {
	/**
	 * nb of type to handle.
	 * 
	 */
	private static final int TYPE_MAP_SIZE = 20;

	/**
	 * type container.
	 * 
	 */
	private static final String[] TYPE_MAP = new String[TYPE_MAP_SIZE];

	/**
	 * object container.
	 * 
	 */
	private static final 
		ContentType[] CONTENT_TYPE_MAP = new ContentType[TYPE_MAP_SIZE];

	/**
	 * basic factory.
	 * 
	 * @param contentType
	 *            uri type
	 * @return type
	 */
	public static ContentType create(final String contentType) {
		int type = getTypeFromString(contentType);
		return CONTENT_TYPE_MAP[type];
	}
	
	/**
	 * basic factory.
	 * 
	 * @param classType
	 *            class type
	 * @return type
	 */
	public static ContentType create(final Class<?> classType) {
		int type = getTypeFromString(classType.getName());
		return CONTENT_TYPE_MAP[type];
	}

	/**
	 * extract type from string.
	 * 
	 * @param contentType
	 *            uri type
	 * @return string type
	 */
	private static String extractType(final String contentType) {
		int idxBegin = contentType.indexOf("/");
		if (idxBegin < 0) {
			idxBegin = 0;
		} else {
			idxBegin += 1;
		}

		int idxEnd = contentType.indexOf(";", idxBegin);
		if (idxEnd < 0) {
			idxEnd = contentType.length();
		}

		return contentType.substring(idxBegin, idxEnd);
	}

	/**
	 * Used to avoid too many String object.
	 * 
	 * @param contentType
	 *            type
	 * @return uri type
	 */
	private static int getTypeFromString(final String contentType) {
		String type = extractType(contentType);
		int i;
		for (i = 0; (i < TYPE_MAP_SIZE) && (TYPE_MAP[i] != null); i++) {
			if (type.equals(TYPE_MAP[i])) {
				return i;
			}
		}

		if (i == TYPE_MAP_SIZE) {
			throw new RuntimeException("TypeMapSize[" + TYPE_MAP_SIZE
					+ "] is reached");
		}

		TYPE_MAP[i] = type;
		CONTENT_TYPE_MAP[i] = new ContentType(i);
		return i;
	}

	/**
	 * type as number.
	 */
	private int type = -1;

	/**
	 * default constructor.
	 * 
	 * @param aType
	 *            as number
	 */
	private ContentType(final int aType) {
		this.type = aType;
	}

	@Override
	public String toString() {
		if (type >= 0) {
			return TYPE_MAP[type];
		} else {
			return "unknown";
		}
	}

	/**
	 * clean stored type.
	 * 
	 */
	public static void clean() {
		for (int i = 0; (i < TYPE_MAP_SIZE) && (TYPE_MAP[i] != null); i++) {
			TYPE_MAP[i] = null;
		}

		for (int i = 0; (i < TYPE_MAP_SIZE) 
					&& (CONTENT_TYPE_MAP[i] != null); i++) {
			CONTENT_TYPE_MAP[i] = null;
		}
	}
}
